#include "Time.h"

void IRAM_ATTR Btu_timerIsr(void *arg);
void IRAM_ATTR BeepLed_timerIsr(void *arg);

void Time_Init(void){					//定时器初始化
	timer_config_t config = {
		.alarm_en = TIMER_ALARM_EN,		//设置开启警报
		.counter_en = TIMER_PAUSE,		//使能计数器
		.counter_dir = TIMER_COUNT_UP,	//计数方向
		.auto_reload = 1,				//设置自动重载计数器
	};

	//-----------------------------------定时器组1-----------------------------------
	//按键定时器
	config.divider = 80;				//分频系数（从80Mhz分）1us
	timer_init(Timer0_group, Timer0_Button, &config);
	timer_set_counter_value(Timer0_group, Timer0_Button, 0x00000000ULL);//指定计时器的初始计数器值
	timer_set_alarm_value(Timer0_group, Timer0_Button, 10000);	//设置警报值	10ms
	timer_enable_intr(Timer0_group, Timer0_Button);			//使能定时器中断
	timer_isr_register(Timer0_group, Timer0_Button, Btu_timerIsr, &config, ESP_INTR_FLAG_IRAM, NULL);//注册定时器中断处理程序
	timer_start(Timer0_group, Timer0_Button);					//开启定时器  	  timer_pause(Timer0_group, Timer0_Button);//关闭

	//-----------------------------------定时器组2-----------------------------------
	//LED灯定时器
	config.divider = 80;				//分频系数（从80Mhz分）1us
	timer_init(Timer0_group, Timer0_BeepLed, &config);
	timer_set_counter_value(Timer0_group, Timer0_BeepLed, 0x00000000ULL);//指定计时器的初始计数器值
	timer_set_alarm_value(Timer0_group, Timer0_BeepLed, 100);	//设置警报值 0.1ms
	timer_enable_intr(Timer0_group, Timer0_BeepLed);			//使能定时器中断
	timer_isr_register(Timer0_group, Timer0_BeepLed, BeepLed_timerIsr, &config, ESP_INTR_FLAG_IRAM, NULL);//注册定时器中断处理程序
	timer_start(Timer0_group, Timer0_BeepLed);					//开启定时器  	  timer_pause(Timer0_group, Timer0_BeepLed);//关闭
}

//-----------------------------------按键中断函数-----------------------------------
uint32_t Tim_Countdown=0;
void IRAM_ATTR Btu_timerIsr(void *arg){						//10ms单位
	static uint8_t ResetESP_flag=0; 					    //用于防止出现按一次响应多次的现象，只能在松手之后才可以继续进行
	static uint8_t BtuPressFlag=0;							//按键触发标志
	static uint16_t BtuPress_count=0;						//按键时长计数
	
	timer_group_clr_intr_status_in_isr(Timer0_group, Timer0_Button);
	timer_group_enable_alarm_in_isr(Timer0_group, Timer0_Button);

	//----------------------↓按键控制↓----------------------//
	if(!Btu_Get)BtuPressFlag=1;//按键按下,按键标志位置1
	//这里是写法问题。在GD32中，按键按下才会开启定时器，所以能直接根据按键状态判断。这里的定时器是一直开着。
	//假设将BtuPressFlag变量直接设置成!Btu_Get那么当你抬起按键的时候已经无法执行下面的函数。也就是无法识别按键抬起，会形成开机后按键失效的情况
	//但是使用这个变量的话，假设这次中断你抬起按键，变量还是1，不执行上面的赋值，但是执行下面程序，此时检测按键状态才能辨别是否抬起
	if(BtuPressFlag){
		BtuPress_count++;
		if(BtuPress_count>=2&&BtuPress_count<30){		    //当定时器为0.02s但是小于0.3s的时候才开始判断，相当于去抖
			if(MCU_ON_flag){//开机状态下
				if(!ResetESP_flag){
				   ResetESP_flag = 1;
				   ResetESP32StartCnt = 1;
				   ResetESP32count++;					 		//每次按键一次则计数加1
				}
				if(!ReadyPrintFlag){						    //如果不是处于预备打印状态（无照片数据）下按下按键，则发送命令给上位机，提示上位机发送照片
				   if(Btu_Get){									//等待按键松开
					   uint8_t resp_data[4] = {0x6A,0xA6,0x3,0x4}; //发送无照片数据，无法开启打印
					   SendToApp(sizeof(resp_data),resp_data);
				   	   BeepExp_set(50,3);
					   BtuPress_count = 0;
					   BtuPressFlag = 0;
					   ResetESP_flag = 0;
				   }
				}
				else{												//有照片数据
				   if(Btu_Get){						    			//等待按键松开并且MCU是处于开启状态下，则为控制开关打印状态
					   BtuPress_count = 0;
					   BtuPressFlag = 0;
				   	   ResetESP_flag = 0;
				   	   if(!StartPrintFlag){		//开启打印
						   uint8_t resp_data[4] = {0x6A,0xA6,0x3,0x2};//应答打印中
						   SendToApp(sizeof(resp_data),resp_data);
					   	   Tim_Countdown = 0;						//开启打印则清空倒计时
					   	   StartPrintFlag = 1;						//开启打印
						   CountReflash = 1;						//计数器刷新
						   gpio_intr_enable(Pluse_IO);				//允许外部引脚中断
						   Beep_set(100);
						   LED5_ON;									//打印灯亮
				   	   }else{					//关闭打印
						   uint8_t resp_data[4] = {0x6A,0xA6,0x3,0xC};//应答打印结束
						   SendToApp(sizeof(resp_data),resp_data);
						   StartPrintFlag = 0;
						   if(TimCnt_Func&0x02)//计数器处理
							 {//预防按键取消打印出现跳数的问题！！！！
								 if(!CntV.CountDir&&CntV.Initialval!=9999)//递增模式
									  CntV.Initialval=CntV.Initialval-1;
								 else if(CntV.CountDir&&CntV.Initialval!=0)//递减模式
									  CntV.Initialval=CntV.Initialval+1;
							 }
						   gpio_intr_disable(Pluse_IO);				//关闭外部引脚中断
						   Beep_set(100);
						   LED5_OFF;								//打印灯灭
					   }
				   }
				}
			}
		}//按键按下不是立即执行程序，需要大概两秒的时间进行初始化，所以此时按键等待0.5秒执行开机
		else if(BtuPress_count>=50&&!Chg_Get&&!SystemLaunch){		//非充电状态下开机0.5秒，因为系统启动也要时间
			if(BtuPress_count==50){
			    MCU_ON_flag = 1; 									//开机标志位置1
			    Pwr_ON;												//PWR_ON_CTR/IO9引脚设置为高，即开机
		  	    Led_McuOnSta();										//led开机初始运行状态
			    Beep_set(500);
			}
			BtuPress_count = 51;
			if(Btu_Get){//等待按键松开
				SystemLaunch = 1;
				BtuPress_count = 0;
				BtuPressFlag = 0;
			}
		}//因为充着电，所以程序是运行的，已经完成了初始化，控制时间与非充电状态下相同，所以充电是两秒
		else if(BtuPress_count>=200){								//长按2秒判断开关机
			if(BtuPress_count==200){
				if(!MCU_ON_flag){
				    MCU_ON_flag = 1; 								//开机标志位置1
				    SystemLaunch = 1;
				    Pwr_ON;											//PWR_ON_CTR/IO9引脚设置为高，即开机
			  	    Led_McuOnSta();									//led开机初始运行状态
				    Beep_set(500);
				}else{
					MCU_ON_flag = 0; 					 			//开机标志位清0
					SystemLaunch = 0;
					Beep_set(500);
				}
			}
			BtuPress_count = 201;
			if(Btu_Get){//等待按键松开
				BtuPress_count = 0;
				BtuPressFlag = 0;
			}
		}//此处必须增加一个判断按键松开，否则在充电状态下，点击一下就会开机。因为时间不到2秒没有检测抬起，计数就会一直上涨直到大于200开机。
		if(Btu_Get){//等待按键松开
			BtuPress_count = 0;
			BtuPressFlag = 0;
		}
	}
	
	//----------------------↓ESP32复位连按状态↓----------------------//
	static uint16_t Tim_count=0;
	if(ResetESP32StartCnt)
	  {
		 Tim_count++;
		 if(Tim_count>300)							   		//TIM计时3s如果超过了3秒则重新计数
		   {
			  ResetESP32count=0;
			  ResetESP32StartCnt=0;
			  Tim_count=0;
		   }
		 else if(Tim_count<=300&&ResetESP32count>=5)	  	//TIM计时3S内，按键次数达到5或以上的则启动ESP32重置功能
		   {
			  ResetESP32StartCnt=0;
			  Tim_count=0;
		   }
	  }
	
	//------------------------↓自动关机倒计时↓-----------------------//
	if(MCU_ON_flag){//开机状态下
		Tim_Countdown++;
		if(Tim_Countdown>30000){							//打印状态下5分钟无操作则停止打印
			if(StartPrintFlag){
				uint8_t resp_data[4] = {0x6A,0xA6,0x3,0xC};//应答打印结束
				SendToApp(sizeof(resp_data),resp_data);
				StartPrintFlag = 0;
				if(TimCnt_Func&0x02)//计数器处理
				  {//预防取消打印出现跳数的问题！！！！
					  if(!CntV.CountDir&&CntV.Initialval!=9999)//递增模式
						   CntV.Initialval=CntV.Initialval-1;
					  else if(CntV.CountDir&&CntV.Initialval!=0)//递减模式
						   CntV.Initialval=CntV.Initialval+1;
				  }
				gpio_intr_disable(Pluse_IO);			 	//关闭外部引脚中断
				Beep_set(100);
				LED5_OFF;								 	//打印灯灭
			}
			if(Tim_Countdown>180000){						//非打印状态下倒计时30分钟自动关机
				Beep_set(500);
				MCU_ON_flag = 0;						 	//开机标志位清0
			}
		}
	}
	
}
//-----------------------------------蜂鸣器&LED灯中断函数-----------------------------------
void IRAM_ATTR BeepLed_timerIsr(void *arg){	// 0.1ms单位
	timer_group_clr_intr_status_in_isr(Timer0_group, Timer0_BeepLed);
	timer_group_enable_alarm_in_isr(Timer0_group, Timer0_BeepLed);
	//---------------------蜂鸣器程序--------------------- 
		static uint8_t	Beep_IOturn=0;	//蜂鸣器脉冲翻转值
		static uint8_t	Beep_cnt=2,Beep_Lastcnt=2;	//蜂鸣器分贝控制
		if(BePm.runFlag){
			if(BePm.count==0){
				Beep_IOturn=0;Beep_cnt=2;Beep_Lastcnt=Beep_cnt;
				if(BePm.expandCnt==1){//单次响
					BePm.runFlag = 0;
					BePm.countSave = 0;
					//关机写在这里不写在长按关机那里的原因是因为写在长按那里，在主函数里面执行完了就会立刻断电
					//如果响的那一瞬间立刻松手此时蜂鸣器还没滴完就会关机，如果等滴完在松手就正常。写在这里就会正常响完在断电
					if(MCU_ON_flag==0){//非充电下关机蜂鸣器响完之后才关机
						MCU_OFF_flag = 1;
					}
				}else{			   //循环响
					BePm.expandCnt--;//循环次数减一
					BePm.runFlag = 1;//循环跑置1
					BePm.count = 1;//置1是为了可以进入下面的else
					BePm.expWait = 1500;//蜂鸣器循环响的间隔时间：0.15s
				}
			}else{
				if(BePm.expWait){
					BePm.expWait--;
					if(BePm.count==1)
						BePm.count = BePm.countSave;
				}
				else{						
					if(Beep_cnt--)//蜂鸣器高300us,低200us的分贝最合适
						Beep_Ctl(Beep_IOturn=!Beep_IOturn);//蜂鸣器响
					else{
						if(Beep_Lastcnt==2){
							Beep_Lastcnt=1;
							Beep_cnt = Beep_Lastcnt;
						}
						else{
							Beep_Lastcnt=2;
							Beep_cnt = Beep_Lastcnt;
						}
					}
					BePm.count--;
				}
			}
		}
		
	//----------------------开机LED程序-----------------------
		static uint8_t	Led_IOturn=0;	//LED脉冲翻转值
		if(LedPm.twinkle&&LedPm.runcount&&MCU_ON_flag){
			LedPm.runcount--;
			if(!LedPm.runcount){
				Led_IOturn=!Led_IOturn;
				if(LedPm.number&0x01)LED1_Ctl(Led_IOturn);
				if(LedPm.number&0x02)LED2_Ctl(Led_IOturn);
				if(LedPm.number&0x04)LED3_Ctl(Led_IOturn);
				if(LedPm.number&0x08)LED4_Ctl(Led_IOturn);
				if(LedPm.number&0x10)LED5_Ctl(Led_IOturn);
				LedPm.runcount = 5000;//1秒闪烁
			}
		}
		
	//----------------------充电LED程序-----------------------
		static uint8_t ErrorCharge=0;
		if(Chg_Get&&!MCU_ON_flag&&ChargingStart&&LedPm.runcount){//关机&充电状态
			LedPm.runcount--;
			if(!LedPm.runcount){					//IP2326芯片该引脚状态：正常充电为高电平，充满为低电平，异常充电为脉冲
				if(ErrorCharge<6){
					if(ChgFull_Get){				//正常充电
						if(ErrorCharge%2)			//每0.5秒检测一次高低电平变化,检测到超过6次高低电平状态则为异常		
							ErrorCharge++;
					
						if(LedPm.number&0x01){		//灯光跑流水灯
							Led_set(0);LED1_ON;
							LedPm.number = 0x01;
						}
						if(LedPm.number&0x02)LED2_ON;
						if(LedPm.number&0x04)LED3_ON;
						if(LedPm.number&0x08)LED4_ON;
						if(LedPm.number&0x10)LED5_ON;
						LedPm.number <<= 1;//左移
						if(LedPm.number>0x10)LedPm.number = 0x01;
					}
					else{							//充满
						if(!(ErrorCharge%2))
							ErrorCharge++;
						Led_set(1);					//灯光全亮
					}
				}
				else{								//充电异常
					Led_set(ErrorCharge&0x1?(ErrorCharge-- &0x1):(ErrorCharge++ &0x1));
				}
				LedPm.runcount = 5000;				//0.5秒闪烁
			}
		}
		else{
			ChargingStart = 0;
			ErrorCharge = 0;
		}
		
	//----------------------ADC程序-----------------------
		static uint32_t	ADC_TimeCnt=0;
		ADC_TimeCnt++;
		if(ADC_TimeCnt>=100000){				//每10秒发送一次ADC值，前提是非打印中和非传图中
			ADC_TimeCnt = 1;
			adcTimeRead = 1;
		}
		
	//----------------------TimRun程序-----------------------
		static uint32_t	TimRun=0;
		if(esp_tim_run_flg.PrintContinue && PrintEnd){
			TimRun++;
			  if(Print_Timecount<=1){
			  	 if(INPulse_count>=10){			//滚轮防抖
				 	TimRun=0;
					INPulse_count=0;
				 }
             	 if(TimRun>=2000){
				 	PrintEnd = 0;				//默认连续打印间隔200ms继续
				 	CountReflash = 1;			//计数器刷新
             	 }
              }
             else{
				 if(TimRun>=Print_Timecount*10){//客户自行设置连续打印间隔时间
					 PrintEnd = 0;
					 CountReflash = 1;
				 }
			 }
		}
		else TimRun = 0;
		//-------------------串口打印-----------------------
		static uint16_t	USB_TimeCnt=0;
		if(USB_Print_Stata){
			if(!PrintEnd){
				USB_TimeCnt++;			
				if(USB_TimeCnt>=(USB_DelayTime/100)){				
					if(StartPrintFlag){//开启打印
						INPulse_count++;
						testFlag = 1;
						if(INPulse_count>=((data_length/39)+105)){			//打印完成
							INPulse_count = 0;
							PrintEnd = 1;
							Beep_set(100);
							if(Print_ContinueFlag){							//判断是否连续打印
								esp_tim_run_flg.PrintContinue = 1;
							}else{
								esp_tim_run_flg.PrintContinue = 0;
								StartPrintFlag = 0;					   	//关闭打印
								gpio_intr_disable(Pluse_IO);				//关闭外部引脚中断
								uint8_t resp_data[4] = {0x6A,0xA6,0x3,0xC};	//打印结束指令
								SendToApp(sizeof(resp_data),resp_data);
								LED5_OFF;								   	//打印灯灭
							}
						}
						if(INPulse_count>=105){//滑动脉冲数计数值大于100的时候才开始打印，这个105刚好是Pen的机身侧边起点开始打印
							Print_data(&RxBuf[39*(INPulse_count-105)+7]);//需要除去包头长度7
							testFlag = 1;}
					}
					USB_TimeCnt = 0;
				}
				
			}
		}	
}

